package cn.lzj.ymcc.service.impl;

import cn.lzj.ymcc.config.HighlightResultMapper;
import cn.lzj.ymcc.doc.CourseDoc;
import cn.lzj.ymcc.dto.CourseSearchESParamDto;
import cn.lzj.ymcc.repository.CourseElasticsearchRepository;
import cn.lzj.ymcc.result.PageList;
import cn.lzj.ymcc.service.ICourseESService;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

@Service
public class CourseESServiceImpl implements ICourseESService {
    @Autowired
    private CourseElasticsearchRepository repository;
    @Autowired
    private ElasticsearchRestTemplate templates;
    @Autowired
    private HighlightResultMapper resultMapper;

    @Override
    public void save(CourseDoc doc) {
        repository.save(doc);
    }

    @Override
    public void offLineCourse(Long id) {
        repository.deleteById(id);
    }

    @Override
    public PageList<CourseDoc> search(CourseSearchESParamDto dto) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        //指定分页方式============================================
        builder.withPageable(PageRequest.of(dto.getPage() - 1, dto.getRows()));
        //指定排序的条件
        builder.withSort(new FieldSortBuilder("price").order(SortOrder.DESC));
        
        //指定排序方式============================================
        addSort(dto, builder);

        //指定高亮条件============================================
        highLightquery(builder);

        //指定查询条件============================================
        queryTerm(dto, builder);

        
        NativeSearchQuery searchQuery = builder.build();

        //Page<CourseDoc> page = repository.search(searchQuery);
        AggregatedPage<CourseDoc> page = templates.queryForPage(searchQuery, CourseDoc.class, resultMapper);

        return new PageList(page.getTotalElements(), page.getContent());
    }

    private void highLightquery(NativeSearchQueryBuilder builder) {
        builder.withHighlightFields(new HighlightBuilder.Field("name")
                .preTags("<font style='color:red'>").postTags("</font>"));

    }

    private void queryTerm(CourseSearchESParamDto dto, NativeSearchQueryBuilder builder) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (StringUtils.isNotBlank(dto.getKeyword())) {
            boolQuery.must(QueryBuilders.matchQuery("name", dto.getKeyword()));
        }
        if (dto.getCourseTypeId() != null) {
            boolQuery.filter(QueryBuilders.termQuery("courseTypeId", dto.getCourseTypeId()));
        }
        if (StringUtils.isNotBlank(dto.getGradeName())) {
            boolQuery.filter(QueryBuilders.termQuery("gradeName", dto.getGradeName()));
        }
        if (dto.getPriceMax() != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(dto.getPriceMax()));
        }
        if (dto.getPriceMin() != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(dto.getPriceMin()));
        }
        builder.withQuery(boolQuery);
    }

    private void addSort(CourseSearchESParamDto dto, NativeSearchQueryBuilder builder) {

        //指定排序条件=====
        if (StringUtils.isNotBlank(dto.getSortField())) {
            String fieldName = null;
            switch (dto.getSortField().toLowerCase()) {
                case "xl":
                    fieldName = "saleCount";
                    break;
                case "pl":
                    fieldName = "commentCount";
                    break;
                case "jg":
                    fieldName = "price";
                    break;
                case "rq":
                    fieldName = "viewCount";
                    break;
                case "xp":
                    fieldName = "onlineTime";
                    break;
                default:
            }
            if (fieldName != null) {

                SortOrder sortOrder = SortOrder.DESC;
                if (StringUtils.isNotBlank(dto.getSortType()) && dto.getSortType().equalsIgnoreCase("asc")) {
                    sortOrder = SortOrder.ASC;
                }
                builder.withSort(new FieldSortBuilder(fieldName).order(sortOrder));
            }

        }

    }
}
